package practise.mulitThreads.ConcurrentInPractice.Memorizer;

import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
 * Created by richard on 6/13/14.
 */
public class Memorizer<K> {
    private ConcurrentHashMap<K, FutureTask<Integer>> cache = new ConcurrentHashMap<>();

    public Integer get(K key) {
        FutureTask<Integer> futureTask = cache.get(key);
        try {
            if (futureTask != null) {
                if(futureTask.isCancelled()){
                    cache.remove(key);
                    return null;
                }
                if (futureTask.isDone()) {
                    return futureTask.get();
                }
            }
        } catch (InterruptedException e) {
            //
        } catch (ExecutionException e) {
            //
        }
        return null;
    }

    public void put(K key, ComputeObject object){
        if(key == null || object==null) throw new NullPointerException("Key or value cannot be null");
        //create a callable task
        Callable<Integer> result = new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                return object.compute();
            }
        };
        FutureTask<Integer> value = new FutureTask<>(result);
        FutureTask<Integer> f = cache.putIfAbsent(key,value);
        if(f==null)//we don't have that key in the cache
            new Thread(value).start();
        get(key);
    }
}
